package com.xb.chain.block;

import com.xb.chain.entity.Block;
import com.xb.chain.entity.Result;
import com.xb.chain.pow.PowResult;
import com.xb.chain.pow.ProofOfWork;
import com.xb.chain.transaction.Transaction;
import com.xb.chain.utils.BlockUtils;
import lombok.extern.slf4j.Slf4j;

import java.math.BigDecimal;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @author xiaobin
 * @date 2020/2/19 16:33
 * @desc 操作区块链
 */
@Slf4j
public abstract class AbstractBlockChain {

    public static CopyOnWriteArrayList<Block> list = new CopyOnWriteArrayList<Block>();

    /**
     * 创世区块
     */
    public Block startBlock() {
        List<Transaction> collect = Stream.of(new Transaction("", "xiaobin", new BigDecimal(100))).collect(Collectors.toList());
        Block block = new Block("", collect);
        Block generateBlock = generateBlock(block);
        this.list.add(generateBlock);
        return generateBlock;
    }

    /**
     * 添加新区块(挖矿)
     */
    public abstract Block mineBlock(List<Transaction> transactions);


    /**
     * 校验整条链
     */
    public static Result validataBlockChain() {
        return BlockUtils.validateBlockChain(AbstractBlockChain.list);
    }

    /**
     * 转账操作
     */
    public abstract Transaction transfer(String from, String to, BigDecimal value);

    /**
     * 查询余额
     */
    public abstract BigDecimal getBalance(String address);


    /**
     *  获取当前区块链高度
     */
    public Integer getBlockNumber(){
        return list.size();
    }

    public void currentBlockInfo() {
        this.list.stream().forEach((item) -> {

            log.info(item.toString());
        });
    }


    protected Block generateBlock(Block block) {
        ProofOfWork pow = ProofOfWork.newPow(block);
        PowResult compute = pow.compute();
        block.setBlockHash(compute.getHash());
        block.setNonce(compute.getNonce());
        return block;
    }

}
